package io.easyspring.demo.common;

import io.easyspring.framework.common.enums.ErrorResultEnum;
import io.easyspring.framework.common.exception.AuthenticationException;
import io.easyspring.framework.common.exception.CommonException;
import io.easyspring.framework.common.exception.ValidationException;
import io.easyspring.framework.common.result.ErrorResult;
import io.easyspring.framework.common.result.ExceptionResult;
import io.easyspring.framework.common.result.builder.ExceptionResultBuilder;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.security.auth.login.LoginException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;

/**
 * 异常返回信息格式化的类
 * 注意: 在覆盖源方法的时候, 需要写明 bean 的名称, 否则会使用默认的 builder 进行格式化数据
 *
 * @author summer
 * @version 2.0.0-RELEASE
 * DateTime 2019-05-24 17:29
 */
@Component(ExceptionResultBuilder.BEAN_NAME)
public class DesignExceptionResultBuilder implements ExceptionResultBuilder {

    /**
     * 重写格式化异常返回信息的方法
     *
     * @param request 请求对象
     * @param response 返回对象
     * @param exception 异常对象
     * @return io.easyspring.framework.common.result.ExceptionResult
     * Author summer
     * Version 2.0.0-RELEASE
     * DateTime 2019-05-24 17:30
     */
    @Override
    public ExceptionResult builder(HttpServletRequest request, HttpServletResponse response, Exception exception){
        // 创建异常返回对象
        ExceptionResult exceptionResult = new ExceptionResult();
        // 设置错误码(默认 500)
        exceptionResult.setHttpStatus(HttpStatus.INTERNAL_SERVER_ERROR);

        // 创建错误返回新
        ErrorResult errorResult = null;

        /* 如果异常信息为空 */
        if (exception == null) {

            errorResult = ErrorResult.error(ErrorResultEnum.ERROR);

        /* 处理自定义的数据校验异常异常 */
        }else if (exception instanceof ValidationException) {

            ValidationException validationException =
                    (ValidationException) exception;
            // 封装错误信息
            errorResult = ErrorResult.error(validationException);
            // 设置错误码
            exceptionResult.setHttpStatus(HttpStatus.BAD_REQUEST);

        /* 处理登录状态丢失的异常 */
        }else if (exception instanceof AuthenticationException) {

            AuthenticationException authenticationException = (AuthenticationException) exception;
            // 封装错误信息
            errorResult = ErrorResult.error(authenticationException);
            // 设置错误码
            exceptionResult.setHttpStatus(HttpStatus.UNAUTHORIZED);

        /* 处理登录异常 */
        }else if (exception instanceof LoginException) {

            LoginException loginException = (LoginException) exception;
            // 封装错误信息
            errorResult = ErrorResult.error(ErrorResultEnum.USER_LOGIN_ERROR);
            // 设置错误码
            exceptionResult.setHttpStatus(HttpStatus.INTERNAL_SERVER_ERROR);

        /* 处理数据校验异常 */
        } else if (exception instanceof BindException) {

            // 转换异常为其数据校验异常
            BindingResult bindingResult = ((BindException) exception).getBindingResult();
            // 创建参数校验的异常对象
            ValidationException validationException = new ValidationException(bindingResult);
            // 封装错误信息
            errorResult = ErrorResult.error(validationException);
            // 设置错误码
            exceptionResult.setHttpStatus(HttpStatus.BAD_REQUEST);

        /* 数据校验异常 */
        } else if (exception instanceof MethodArgumentNotValidException) {
            // 转换异常为其数据校验异常
            BindingResult bindingResult = ((MethodArgumentNotValidException) exception).getBindingResult();
            // 创建参数校验的异常对象
            ValidationException validationException = new ValidationException(bindingResult);
            // 封装错误信息
            errorResult = ErrorResult.error(validationException);
            // 设置错误码
            exceptionResult.setHttpStatus(HttpStatus.BAD_REQUEST);

        /* 约束不匹配的异常 */
        } else if (exception instanceof ConstraintViolationException){
            // 创建参数校验的异常对象
            ValidationException validationException = new ValidationException((ConstraintViolationException) exception);
            // 封装错误信息
            errorResult = ErrorResult.error(validationException);
            // 设置错误码
            exceptionResult.setHttpStatus(HttpStatus.BAD_REQUEST);

        /* 处理路径未找到的问题 */
        } else if (exception instanceof NoHandlerFoundException) {

            // 封装错误信息
            errorResult = ErrorResult.error(exception.getMessage());
            // 设置错误码
            exceptionResult.setHttpStatus(HttpStatus.NOT_FOUND);

        /* 处理基础异常 */
        }else if (exception instanceof CommonException) {

            CommonException commonException = (CommonException) exception;
            // 封装错误信息
            errorResult = ErrorResult.error(commonException);
            // 设置错误码
            exceptionResult.setHttpStatus(HttpStatus.INTERNAL_SERVER_ERROR);

        /* 处理其他未知异常 */
        } else {

            // 封装错误信息
            errorResult = ErrorResult.error(ErrorResultEnum.ERROR.getErrorMessage(), exception.getMessage());
        }

        // 设置错误返回信息
        exceptionResult.setErrorResult(errorResult);

        return exceptionResult;
    }
}
